package com.cl;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelReader;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.read.metadata.ReadSheet;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.domain.RecordDomain;
import com.listener.RecordDomainListener;
import com.sun.org.apache.xpath.internal.operations.Or;
import org.apache.poi.hssf.dev.RecordLister;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;

/**
 * 删除指定目录及其子目录下.md文件中未被引用的图片
 * @author xiaoybb
 * @date 2021-01-13
 * @version 2.0 之前只能将一个目录下的asset目录进行过滤，现在可以递归至下面的子文件。
 * @version 2.1 再增加写入excel记录功能
 */
public class DelImagesUtil {
    private int count;
    private double sizeCount;

    /**
     * 获取内容列表。拿到目录下所有文件，如果是markdown文件就读取字符串内容，保存到列表中。
     * @date 2020/9/22 11:58
     * @param
     * @return java.util.ArrayList<java.lang.String>
     */
    public ArrayList<String> getContextList(File dir) throws IOException {
        File[] files = dir.listFiles();
        ArrayList<String> contentStrings = new ArrayList<>();
        for (File file : files) {
            if (file.isFile() && file.getName().endsWith(".md")) {
                String content = readFile(file);
                contentStrings.add(content);
            }
        }
        return contentStrings;
    }

    /**
     * 读取文件。字符流
     * @date 2020/9/22 12:01
     * @param file
     * @return java.lang.String
     */
    public String readFile(File file) throws IOException {
        FileReader fr = new FileReader(file);
        BufferedReader br = new BufferedReader(fr);

        String str;
        StringBuilder sb = new StringBuilder();
        while ((str=br.readLine()) != null) {
            sb.append(str);
        }
        String result = new String(sb);
        br.close();
        fr.close();
        return result;
    }

    /**
     * 获取assets目录下所有的图片名
     * @date 2020/9/22 12:11
     * @param
     * @return java.util.ArrayList<java.lang.String>
     */
    public ArrayList<File> getImgFileList(String filepath) throws IOException {
        File dir = new File(filepath+"\\assets");
        File[] files = dir.listFiles();
        ArrayList<File> imgFileList = new ArrayList<>();

        if (files==null) {
            return new ArrayList<File>();
        }

        for (File file : files) {
            boolean isImg = file.getName().endsWith(".jpg") || file.getName().endsWith(".png") || file.getName().endsWith(".jpeg") || file.getName().endsWith(".bmp") || file.getName().endsWith(".gif");
            if (file.isFile() && isImg) {
                imgFileList.add(file);
            }
        }
        return imgFileList;
    }

    /**
     * 递归遍历一个文件夹下的所有文件
     * @date 2021/1/13
     * @return void
     */
    public void recursionDel(File file) {
        if (file.isDirectory()) {
            // 是目录，进行删除图片操作，然后打开目录，递归下面的子文件。
            try {
                processDel(file);
            } catch (IOException e) {
                System.err.println("processDel方法异常");
            }
            File[] files = file.listFiles((pathname) -> {
                return pathname.isDirectory() && !pathname.getName().equals("assets");
            });
            for (File subFile: files) {
                recursionDel(subFile);
            }
        }
    }

    /**
     * 删除当前目录assets中未被使用的图片
     */
    public void processDel(File file) throws IOException {
        /*
         * 获取一个目录下的assets目录，遍历里面的图片名，每一次遍历都遍历该目录下的内容列表，
         * 判断是否包含该图片名
         */
        ArrayList<File> imgFileList = getImgFileList(file.getPath());
        ArrayList<String> contextList = getContextList(file);
        ArrayList<File> delFileList = new ArrayList<>();
        for (File imgFile : imgFileList) {
            boolean flag = true;
            for (String context : contextList) {
                if (context.contains(imgFile.getName())) {
                    flag = false;
                    break;
                }
            }
            if (flag) {
                delFileList.add(imgFile);
            }
        }

        // 获得了最终需要删除的列表，进行删除
        for (File delFile : delFileList) {
            if (delFile.exists()) {
                sizeCount += delFile.length();
                delFile.delete();
                count++;
            }
        }
    }

    /**
     * 使用excel记录清理图片的记录
     * @date 2021/1/15
     * @param path
     * @return void
     */
    private void handleLog(String path) {
        String file = path + "\\record.xlsx";

        // 准备数据
        LocalDateTime localDateTime = LocalDateTime.now();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        String dateStr = localDateTime.format(formatter);

        sizeCount = sizeCount/(1024.0*1024);
        BigDecimal bigDecimal = new BigDecimal(sizeCount);
        sizeCount = bigDecimal.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();

        RecordDomain record = new RecordDomain(dateStr, count, sizeCount);
        ArrayList<RecordDomain> dataList = new ArrayList<>();
        dataList.add(record);

        File excelFile = new File(file);
        ArrayList<RecordDomain> originList = null;
        if (excelFile.exists() && excelFile.length()!=0) {
            // 读取excel
            originList = readExcel(file);
            originList.addAll(dataList);
            EasyExcel.write(file, RecordDomain.class).sheet("删除图片日志").doWrite(originList);
            return;
        }

        // 写入excel
        EasyExcel.write(file, RecordDomain.class).sheet("删除图片日志").doWrite(dataList);
    }

    private ArrayList<RecordDomain> readExcel(String file) {
        // 写法1：
        // 这里 需要指定读用哪个class去读，然后读取第一个sheet 文件流会自动关闭
        RecordDomainListener listener = new RecordDomainListener();
        EasyExcel.read(file, RecordDomain.class, listener).sheet("删除图片日志").doRead();
        ArrayList<RecordDomain> list = listener.getList();
        return list;
    }

    /**
     * 主函数，使用时输入路径参数即可。
     * @date 2021/1/15
     * @param args
     * @return void
     */
    public static void main(String[] args) {
        DelImagesUtil util = new DelImagesUtil();
        String basePath = "C:\\XYBB\\我的坚果云\\note";
        File dir = new File(basePath);
        util.recursionDel(dir);
        util.handleLog(basePath);
    }
}
